package com.senven.books.modules.system.log.aspect;

import cn.hutool.core.util.URLUtil;
import com.senven.books.modules.system.log.annotation.SysLogInfo;
import com.senven.books.modules.system.log.entity.SysLog;
import com.senven.books.modules.system.log.event.SysLogEvent;
import com.senven.books.modules.system.log.util.SessionUtil;
import com.senven.books.modules.system.log.util.SpringContextHolder;
import com.senven.books.utils.ResultVO;
import com.senven.books.utils.UserContextHolder;
import com.senven.books.utils.WebUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author longshengyi
 * @date 2021/8/13 0013
 **/
@Aspect
@Component
public class SysLogAspect {
    private static final Logger log = LoggerFactory.getLogger(SysLogAspect.class);
    private SysLog sysLog;

    public SysLogAspect() {
    }

    @Pointcut("@annotation(com.senven.books.modules.system.log.annotation.SysLogInfo)")
    public void sysLogAspect() {
    }

    @Before("sysLogAspect()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        this.sysLog = new SysLog();
        SysLogInfo annSysLog = ((MethodSignature)joinPoint.getSignature()).getMethod().getAnnotation(SysLogInfo.class);
        HttpServletRequest request = SessionUtil.getRequest();
        String category = annSysLog.type();
        String operationType = "";
        String content = annSysLog.content();



        if (category == null || "".equals(category)) {
            category = "系统日志";
        }

        this.sysLog.setCategory(category);
        this.sysLog.setContent(content);
        this.sysLog.setUserName(UserContextHolder.getInstance().getUsername());

        this.sysLog.setCreateTime(new Date());
        this.sysLog.setMethod(request.getMethod());
        this.sysLog.setUserAgent(request.getHeader("user-agent"));
        this.sysLog.setRequestIp(WebUtils.getRequestIp(request));
        this.sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));
        this.sysLog.setMethodClass(joinPoint.getTarget().getClass().getName());
        this.sysLog.setMethodName(joinPoint.getSignature().getName());
        this.sysLog.setParams(WebUtils.getRequestParamString(request));
    }

    @AfterReturning(
            returning = "ret",
            pointcut = "sysLogAspect()"
    )
    public void doAfterReturning(Object ret) {
        this.sysLog.setRunTime(System.currentTimeMillis() - this.sysLog.getCreateTime().getTime());
        if ("".equals(this.sysLog.getContent()) && ret instanceof ResultVO) {
            String content = ((ResultVO)ret).getMsg();
            this.sysLog.setContent(content);
        }

        SpringContextHolder.publishEvent(new SysLogEvent(this.sysLog));
    }

    @AfterThrowing(
            pointcut = "sysLogAspect()",
            throwing = "e"
    )
    public void doAfterThrowable(Throwable e) {
        this.sysLog.setRunTime(System.currentTimeMillis() - this.sysLog.getCreateTime().getTime());
        if ("".equals(this.sysLog.getContent())) {
            this.sysLog.setContent(e.getMessage());
        }

        this.sysLog.setStatus(1);
        this.sysLog.setStackTrace(e.getMessage());
        SpringContextHolder.publishEvent(new SysLogEvent(this.sysLog));
    }
}
